package com.mzplayer.player;

import android.content.Context;
import android.content.res.AssetManager;
import android.media.AudioManager;
import android.util.Log;
import android.view.Surface;

import com.mzplayer.utils.MediaData;
import com.mzplayer.utils.MediaStream;
import com.mzplayer.utils.Util;

import java.io.IOException;

import tv.danmaku.ijk.media.player.IMediaPlayer;
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
import tv.danmaku.ijk.media.player.IjkTimedText;

public class IJKMediaPlayer implements MediaPlayer, IMediaPlayer.OnPreparedListener, IMediaPlayer.OnVideoSizeChangedListener, IMediaPlayer.OnCompletionListener, IMediaPlayer.OnErrorListener, IMediaPlayer.OnInfoListener, IMediaPlayer.OnLoadingFlushListener, IMediaPlayer.OnBufferingUpdateListener, IMediaPlayer.OnTimedTextListener {
    private IjkMediaPlayer ijkMediaPlayer;
    private Callback callback;
    private final Context context;
    public IJKMediaPlayer(Context context) {
        this.context = context;
        ijkMediaPlayer = new IjkMediaPlayer();
        //ijk关闭log
        IjkMediaPlayer.native_setLogLevel(IjkMediaPlayer.IJK_LOG_SILENT);

        //画面质量 视频格式
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", IjkMediaPlayer.SDL_FCC_RV32);
        //直接播放 1为一进入就播放,0为进入时不播放
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 0);
        //域名检测
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "http-detect-range-support", 0);
        // 解决m3u8文件拖动问题 比如:一个3个多少小时的音频文件，开始播放几秒中，然后拖动到2小时左右的时间，要loading 10分钟
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "fflags", "fastseek");
        //设置是否开启环路过滤: 0开启，画面质量高，解码开销大，48关闭，画面质量差点，解码开销小
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 48);
        //每处理一个packet之后刷新io上下文立即清理数据包来减少等待时长
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "flush_packets", 1);
        //播放重连次数1?5?
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "reconnect", 1);
        //跳帧处理（-1~120）。CPU处理慢时，进行跳帧处理，保证音视频同步,默认1 网络不好的情况下进行丢包
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", 1);
        //因为项目中多次调用播放器，有网络视频，resp，本地视频，还有wifi上http视频，所以得清空DNS才能播放WIFI上的视频 http重定向https
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "dns_cache_clear", 1);
        //超时设置
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "timeout", 30000);

        //预读的 packet 超过 MIN_FRAMES 个，那么 ffplay 就会停止预读(取值2-50000) 控制视频缓存
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "min-frames", 300);
        //播放前的探测Size，默认是1M, 改小一点会出画面更快
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", 512*1024);
        //最大缓冲大小
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max-buffer-size", 1024*1024);
        //最大缓存时长;
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max_cached_duration", 30000);

        //是否开启缓存，一般直播项目会开启，达到秒开的效果，不过带来了播放丢帧卡顿的体验 关闭播放器缓冲
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering", 1);
    }

    @Override
    public void setDataSource(MediaData mediaData) throws IOException {
        if(ijkMediaPlayer!=null) {
            if(mediaData==null) {
                throw new IOException();
            }
            int mt = mediaData.getType();
            if (mt == MediaData.NORMAL) {
                ijkMediaPlayer.setDataSource(mediaData.getPath(), mediaData.getHeader());
            } else {
                ijkMediaPlayer.setDataSource(new MediaStream(MediaData.ASSET == mt ? context.getAssets().open(mediaData.getPath(), AssetManager.ACCESS_RANDOM) : MediaData.RAW == mt ? context.getResources().openRawResource(Util.getResourcesIndex(context, mediaData.getPath(), "raw")) : null));
            }
        }
    }

    @Override
    public void prepareAsync() {
        if(ijkMediaPlayer!=null) {
            if (callback != null) {
                callback.onPreparing();
            }
            ijkMediaPlayer.setOnPreparedListener(this);
            ijkMediaPlayer.setOnVideoSizeChangedListener(this);
            ijkMediaPlayer.setOnCompletionListener(this);
            ijkMediaPlayer.setOnErrorListener(this);
            ijkMediaPlayer.setOnInfoListener(this);
            ijkMediaPlayer.setOnBufferingUpdateListener(this);
            ijkMediaPlayer.setOnLoadingFlushListener(this);
            ijkMediaPlayer.setOnTimedTextListener(this);
            ijkMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            ijkMediaPlayer.prepareAsync();
        }
    }

    @Override
    public void reset() {
        if(ijkMediaPlayer!=null) {
            ijkMediaPlayer.reset();
        }
    }

    @Override
    public boolean isPlaying() {
        if(ijkMediaPlayer!=null) {
            return ijkMediaPlayer.isPlaying();
        }
        return false;
    }

    @Override
    public void start() {
        if(ijkMediaPlayer!=null) {
            ijkMediaPlayer.start();
        }
    }

    @Override
    public void pause() {
        if(ijkMediaPlayer!=null) {
            ijkMediaPlayer.pause();
        }
    }

    @Override
    public void stop() {
        if(ijkMediaPlayer!=null) {
            ijkMediaPlayer.stop();
        }
    }

    @Override
    public void seekTo(long j) {
        if(ijkMediaPlayer!=null) {
            ijkMediaPlayer.seekTo(j);
        }
    }

    @Override
    public long getCurrentPosition() {
        if(ijkMediaPlayer!=null) {
            return ijkMediaPlayer.getCurrentPosition();
        }
        return 0;
    }

    @Override
    public long getDuration() {
        if(ijkMediaPlayer!=null) {
            return ijkMediaPlayer.getDuration();
        }
        return 0;
    }

    @Override
    public void setSurface(Surface surface) {
        if(ijkMediaPlayer!=null) {
            ijkMediaPlayer.setSurface(surface);
        }
    }

    @Override
    public void setSpeed(float speed) {
        if(ijkMediaPlayer!=null) {
            ijkMediaPlayer.setSpeed(speed);
        }
    }

    @Override
    public long getTcpSpeed() {
        if(ijkMediaPlayer!=null) {
            return ijkMediaPlayer.getTcpSpeed();
        }
        return 0;
    }

    @Override
    public void release() {
        if(ijkMediaPlayer!=null) {
            ijkMediaPlayer.release();
            ijkMediaPlayer = null;
        }
    }

    @Override
    public void setCallback(Callback callback) {
        this.callback = callback;
    }

    @Override
    public void usingMediaCodec() {
        if (ijkMediaPlayer!=null) {
            //jkPlayer支持硬解码和软解码。 软解码时不会旋转视频角度这时需要你通过onInfo的what == IMediaPlayer.MEDIA_INFO_VIDEO_ROTATION_CHANGED去获取角度，自己旋转画面。或者开启硬解硬解码，不过硬解码容易造成黑屏无声（硬件兼容问题），下面是设置硬解码相关的代码
            ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);
            //自动旋屏
            ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 1);
            //处理分辨率变化
            ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-handle-resolution-change", 1);
        }
    }

    @Override
    public void rtspUsingTCP() {
        //如果是rtsp协议，可以优先用tcp(默认是用udp)
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_transport", "tcp");
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_flags", "prefer_tcp");
    }

    @Override
    public void onPrepared(IMediaPlayer mp) {
        if (callback != null) {
            callback.onPrepared();
        }
    }

    @Override
    public void onVideoSizeChanged(IMediaPlayer mp, int width, int height, int sar_num, int sar_den) {
        if (callback != null) {
            callback.onVideoSizeChanged(width, height, sar_num, sar_den);
        }
    }

    @Override
    public void onCompletion(IMediaPlayer mp) {
        if (callback != null) {
            callback.onCompletion();
        }
    }

    @Override
    public boolean onError(IMediaPlayer mp, int what, int extra) {
        if (callback != null) {
            return callback.onError(what, extra);
        }
        return false;
    }
    private boolean isLoading;
    @Override
    public boolean onInfo(IMediaPlayer mp, int what, int extra) {
        if(callback ==null) {
            return false;
        }
        switch (what) {
            case IMediaPlayer.MEDIA_INFO_BUFFERING_START:
                callback.onLoadingStart();
                isLoading = true;
                break;
            case IMediaPlayer.MEDIA_INFO_BUFFERING_END:
                isLoading = false;
                callback.onLoadingEnd();
                break;
            case IMediaPlayer.MEDIA_INFO_VIDEO_ROTATION_CHANGED:
                callback.onVideoRotationChanged(extra);
                break;
        }
        return true;
    }

    @Override
    public void onBufferingUpdate(IMediaPlayer mp, int percent) {
        if (callback != null) {
            callback.onBufferingUpdate(percent);
        }
    }

    @Override
    public void onTimedText(IMediaPlayer mp, IjkTimedText text) {
        if (callback != null&& text!=null) {
            callback.onTimedText(text.getText());
        }
    }

    @Override
    public void onLoadingFlush(IMediaPlayer mp, int percent) {
        if(isLoading&&percent<=100) {
            callback.onLoadingFlush(percent);
        }
    }
}
